#include <stdio.h>
#include <windows.h>

#include "serial.h"

int
init_serial(struct serial_dev *sdev, char *port_name)
{
	DCB dcbSerialParams;
	COMMTIMEOUTS timeouts;

	memset(&dcbSerialParams, 0, sizeof(dcbSerialParams));
	memset(&timeouts, 0, sizeof(timeouts));

	sdev->hSerial = CreateFile(port_name, GENERIC_READ | GENERIC_WRITE,
	    0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);

	if (sdev->hSerial == INVALID_HANDLE_VALUE) {
		fprintf(stderr, "error: could not open serial port\n");
		return -1;
	}

	dcbSerialParams.DCBlength = sizeof(dcbSerialParams);
	if (!GetCommState(sdev->hSerial, &dcbSerialParams)) {
		fprintf(stderr, "error: could not get serial port state\n");
		return -1;
	}

	dcbSerialParams.BaudRate = CBR_57600;
	dcbSerialParams.ByteSize = 8;
	dcbSerialParams.StopBits = ONESTOPBIT;
	dcbSerialParams.Parity = NOPARITY;
	
	if (!SetCommState(sdev->hSerial, &dcbSerialParams)) {
		fprintf(stderr, "error: could not set serial port state\n");
		return -1;
	}

	timeouts.ReadIntervalTimeout = 50;
	timeouts.ReadTotalTimeoutConstant = 200;
	timeouts.ReadTotalTimeoutMultiplier = 10;
	timeouts.WriteTotalTimeoutConstant = 50;
	timeouts.WriteTotalTimeoutMultiplier = 10;

	if (!SetCommTimeouts(sdev->hSerial, &timeouts)) {
		fprintf(stderr, "error: could not set serial port "
		    "timeouts\n");
		return -1;
	}

	EscapeCommFunction(sdev->hSerial, SETRTS);

	return 0;
}

void
close_serial(struct serial_dev *sdev)
{
	CloseHandle(sdev->hSerial);
}

size_t
write_ser(struct serial_dev *sdev, void *buf, size_t len)
{
	DWORD written;

	WriteFile(sdev->hSerial, buf, len, &written, NULL);

	return written;
}

size_t
read_ser(struct serial_dev *sdev, void *buf, size_t len)
{
	DWORD read;

	ReadFile(sdev->hSerial, buf, len, &read, NULL);

	return read;
}

void
ser_flush(struct serial_dev *sdev)
{
	int r;
	char buf[128];

	do {
		r = read_ser(sdev, buf, sizeof(buf));
	} while (r > 0);
}
